home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / NIH Image 1.62b11 / Macros / Plotting Macros < prev    next >
Text File  |  1996-06-10  |  24KB  |  970 lines

  1. macro 'Plot Histogram';
  2. var
  3.   max,scale:real;
  4.   i,margin,width,height:integer;
  5. begin
  6.   SaveState;
  7.   Margin:=10;
  8.   width:=256;
  9.   height:=0.6*256;
  10.   Measure;
  11.   SetForegroundColor(255);
  12.   SetBackgroundColor(0);
  13.   SetLineWidth(1);
  14.   SetNewSize(width+2*margin,height+2*margin);
  15.   MakeNewWindow('Histogram');
  16.   MakeRoi(margin,margin-1,width,height+1);
  17.   DrawBoundary;
  18.   max:=0;
  19.   for i:=1 to 254 do
  20.   if histogram[i]> max then max:=histogram[i];
  21.   scale:=height/max;
  22.   for i:=1 to 254 do begin
  23.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  24.     SetForegroundColor(i);
  25.     fill;
  26.  end;
  27.   SelectAll;
  28.   FlipVertical;
  29.   KillRoi;
  30.   RestoreState;
  31. end;
  32.  
  33. macro 'Stack Histogram';
  34. var
  35.   max,scale:real;
  36.   i,margin,width,height:integer;
  37. begin
  38.   SaveState;
  39.   Margin:=10;
  40.   width:=256;
  41.   height:=0.6*256;
  42.   Measure;
  43.   SetForegroundColor(255);
  44.   SetBackgroundColor(0);
  45.   SetLineWidth(1);
  46.   SetNewSize(width+2*margin,height+2*margin);
  47.   MakeNewWindow('Histogram');
  48.   MakeRoi(margin,margin-1,width,height+1);
  49.   DrawBoundary;
  50.   max:=0;
  51.   for i:=1 to 254 do
  52.   if histogram[i]> max then max:=histogram[i];
  53.   scale:=height/max;
  54.   for i:=1 to 254 do begin
  55.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  56.     SetForegroundColor(i);
  57.     fill;
  58.  end;
  59.   SelectAll;
  60.   FlipVertical;
  61.   KillRoi;
  62.   RestoreState;
  63. end;
  64.  
  65. procedure DoColumnPlot(MaxCount: integer);
  66. {Plots the User1 column in the Results table.}
  67. var
  68.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  69.    width,height,margin,pwidth,pheight:integer;
  70.    y,pbottom, barWidth, barLeft, barTop:integer;
  71.    sum:integer;
  72. begin
  73.   SaveState;
  74.   margin:=40;
  75.   width:=500;
  76.   height:=300;
  77.   sum:=0;
  78.   ymin:=0;
  79.   ymax:=-999999;
  80.   for i:=1 to maxCount do
  81.       if rUser1[i]>ymax then ymax:=rUser1[i];
  82.   xmin:=1;
  83.   xmax:=maxCount;
  84.   SetNewSize(width,height);
  85.   SetForeground(255);
  86.   SetBackground(0);
  87.   MakeNewWindow('Histogram');
  88.   pwidth:=width-2*margin;
  89.   pheight:=height-2*margin;
  90.   pbottom:=margin+pheight;
  91.   xscale:=pwidth/xmax;
  92.   yscale:=pheight/(ymax-ymin);
  93.   barWidth:=round(pwidth/maxCount)+1;
  94.   SetForeground(255);
  95.   SetBackground(0); 
  96.   SetLineWidth(1);
  97.   for i:=0 to maxCount-1 do begin
  98.      barLeft:=margin+i*xscale;
  99.      barTop:=pbottom-(rUser1[i+1]-ymin)*yscale;
  100.      MakeRoi(barLeft, barTop, barWidth, pBottom-barTop);
  101.      fill;
  102.      sum:=sum+(i+1)*rUser1[i+1];
  103.   end;
  104.   KillRoi;
  105.   MoveTo(margin,margin);
  106.   LineTo(margin,margin+pheight);
  107.   SetFont('Geneva');
  108.   SetFontSize(9);
  109.   SetText('Centered');
  110.   MoveTo(margin+4,margin+pheight+12);
  111.   writeln(xmin:1:2);
  112.   MoveTo(margin+pwidth,margin+pheight+12);
  113.   writeln(xmax:1:2);
  114.   SetText('Right Justified');
  115.   MoveTo(margin-2,margin+pheight-5);
  116.   writeln(ymin:1:2);
  117.   MoveTo(margin-2,margin);
  118.   writeln(ymax:1:2);
  119.   MoveTo(margin+pwidth/2-15, margin+pheight+12);
  120.   RestoreState;
  121.   ShowMessage('sum=',sum:1,'\ymax=',ymax:1);
  122. end;
  123.  
  124.  
  125. macro 'Plot Histogram Using Bins';
  126. var
  127.   i, nBins, bin: integer;
  128.   ValuesPerBin, TotalArea: real;
  129.    n, lower, upper, nValues: integer;
  130.    first, last: integer;
  131. begin
  132.   ResetCounter;
  133.   nBins:=GetNumber('Number of Bins (1-256)', 10);
  134.   SetUser1Label('%');
  135.   SetUser2Label('Area');
  136.   Measure;
  137.   TotalArea := rArea[rCount];
  138.   GetThreshold(lower, upper);
  139.   if (lower = 0) and (upper = 0) then
  140.      upper := 255;
  141.   nValues := upper - lower + 1;
  142.   n := 0;
  143.   for i := lower to upper do
  144.      n := n + histogram[i];
  145.   ValuesPerBin := nValues / nBins;
  146.   for bin := 1 to nBins do
  147.       rUser1[bin] := 0;
  148.   {for i := lower to upper do begin
  149.       bin := trunc((i - lower) / ValuesPerBin) + 1;
  150.       rUser1[bin] := rUser1[bin] + Histogram[i];
  151.   end;}
  152.   SaveState;
  153.   SetFont('Monaco');
  154.   SetFontSize(9);
  155.   NewTextWindow('Histogram Data', 280, 450);
  156.   writeln(' Bin    Range   Count   Percent   Area');
  157.   for bin := 1 to nBins do begin
  158.       first := lower + trunc((nValues * (bin - 1)) / nBins);
  159.       last := lower + trunc((nValues * bin) / nBins) -1 ;
  160.       for i := first to last do
  161.          rUser1[bin] := rUser1[bin] + Histogram[i];
  162.       writeln(bin:3, first:6, last:4, rUser1[bin]:8, (rUser1[bin] / n) * 100:8:2, TotalArea * rUser1[bin] / n:10:2);
  163.   end;
  164.   RestoreState;
  165.   for bin := 1 to nBins do
  166.       rUser1[bin] :=  (rUser1[bin] / n) * 100.0;
  167.   for bin := 1 to nBins do
  168.       rUser2[bin] :=  TotalArea * rUser1[bin] / 100;
  169.   SetCounter(nBins);
  170.   DoColumnPlot(nBins);
  171. end;
  172.  
  173.  
  174. procedure DrawPerimeter;
  175. var
  176.   length1, length2: integer;
  177.   dx1, dx2, dy1, dy2: integer;
  178.   dxp1, dxp2, dyp1, dyp2: integer;
  179.   sumdx, sumdy, corners: integer;
  180.   corner: boolean;
  181.   perimeter: real;
  182. begin
  183.   RedLUT[254] := 255;
  184.   GreenLUT[254] := 0;
  185.   BlueLUT[254] := 0;
  186.   SetForeground(254);
  187.   sumdx := 0.0;
  188.   sumdy := 0.0;
  189.   corners := 0;
  190.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  191.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  192.   length1 := abs(dx1) + abs(dy1);
  193.   dxp1 := dx1;
  194.   if dxp1 > 1 then dxp1 := 1;
  195.   if dxp1 < -1 then dxp1 := -1;
  196.   dyp1 := dy1;
  197.   if dyp1 > 1 then dyp1 := 1;
  198.   if dyp1 < -1 then dyp1 := -1;
  199.   corner := false;
  200.   for i := 1 to nCoordinates do begin
  201.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  202.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  203. {showmessage(i, abs(dx1), abs(dy1)); wait(2);}
  204.      sumdx := sumdx + abs(dx1);
  205.      sumdy := sumdy + abs(dy1);
  206.      length2 := abs(dx2) + abs(dy2);
  207.      dxp2 := dx2;
  208.      if dxp2 > 1 then dxp2 := 1;
  209.      if dxp2 < -1 then dxp2 := -1;
  210.      dyp2 := dy2;
  211.      if dyp2 > 1 then dyp2 := 1;
  212.      if dyp2 < -1 then dyp2 := -1;
  213.      if (length1 > 1) or (not corner) then begin
  214.         MoveTo((xCoordinates[i]-dxp1)*scale+10, (yCoordinates[i]-dyp1)*scale+10);
  215.         LineTo((xCoordinates[i]+dxp2)*scale+10, (yCoordinates[i]+dyp2)*scale+10);
  216.         corner := true;
  217.         corners := corners + 1;
  218.      end else
  219.         corner := false;
  220.      dx1 := dx2;
  221.      dy1 := dy2;
  222.      dxp1 := dxp2;
  223.      dyp1 := dyp2;
  224.      length1 := length2;
  225.   end;
  226.   perimeter := sumdx + sumdy;
  227. end;
  228.  
  229. procedure ShowPerimeter;
  230. var
  231.   length1, length2: integer;
  232.   dx1, dx2, dy1, dy2: integer;
  233.   sumdx, sumdy, nCorners: integer;
  234.   corner: boolean;
  235.   perimeter: real;
  236. begin
  237.   sumdx := 0.0;
  238.   sumdy := 0.0;
  239.   nCorners := 0;
  240.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  241.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  242.   length1 := abs(dx1) + abs(dy1);
  243.   corner := false;
  244.   for i := 1 to nCoordinates do begin
  245.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  246.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  247.      sumdx := sumdx + abs(dx1);
  248.      sumdy := sumdy + abs(dy1);
  249.      length2 := abs(dx2) + abs(dy2);
  250.      if (length1 > 1) or (not corner) then begin
  251.         corner := true;
  252.         nCorners := nCorners + 1;
  253.      end else
  254.         corner := false;
  255.      dx1 := dx2;
  256.      dy1 := dy2;
  257.      length1 := length2;
  258.   end;
  259.   perimeter := sumdx + sumdy;
  260.   MoveTo(width/3,height/3 + 40);
  261.   Writeln('perimeter1=', perimeter:1:2);
  262.   Writeln('perimeter2=', perimeter - nCorners * (2 - sqrt(2)):1:2);
  263.   Writeln('perimeter3=', perimeter*0.948 - nCorners * (2 - 1.34):1:2);
  264. end;
  265.  
  266. procedure DrawX(x, y:integer);
  267. begin
  268.   moveto(x+3, y+3);
  269.   lineto(x-3, y-3);
  270.   moveto(x+3, y-3);
  271.   lineto(x-3, y+3);
  272.   lineto(x, y);
  273. end;
  274.  
  275.  
  276. macro 'Plot XY Coordinates [X]';
  277. {Plots the X-Y Coordinates of the current ROI.}
  278. var
  279.   i,w,h,width,height:integer;
  280.   xbase,ybase,RoiWidth,RoiHeight:integer
  281.   x,y,scale,xmax,ymax:real 
  282. begin
  283.   RequiresVersion(1.48);
  284.   if nCoordinates=0 then begin
  285.     beep;
  286.     PutMessage('No X-Y Coordinates available.');
  287.     exit;
  288.   end;
  289.   GetRoi(xbase,ybase,RoiWidth,RoiHeight);
  290.   SaveState;
  291.   InvertY(false);
  292.   xmax:=0;
  293.   ymax:=0;
  294.   for i:=1 to nCoordinates do begin
  295.     x:=xCoordinates[i];
  296.     y:=yCoordinates[i];
  297.     if x>xmax then xmax:=x;
  298.     if y>ymax then ymax:=y;
  299.   end;
  300.   scale:=sqrt((300*300)/(xmax*ymax));
  301.   if (xmax*scale)>500 then scale:=500/xmax;
  302.   if (ymax*scale)>500 then scale:=500/ymax;
  303.   SetForegroundColor(255);
  304.   SetBackgroundColor(0);
  305.   SetNewSize(xmax*scale+20,ymax*scale+20);
  306.   MakeNewWindow('Outline');
  307.   MoveTo(xCoordinates[1]*scale+10,yCoordinates[1]*scale+10);
  308.   for i:=2 to nCoordinates do begin
  309.     LineTo(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  310.     if nCoordinates < 100 then
  311.        DrawX(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  312.   end;
  313.   SetFont('Helvetica');
  314.   SetFontSize(12);
  315.   SetText('No background, Left Justified');
  316.   GetPicSize(width,height);
  317.   MoveTo(width/3,height/3);
  318.   Writeln(nCoordinates:1,' coordinate pairs');
  319.   Writeln('Origin=',xbase:1,', ',ybase:1);
  320.   Writeln('xmax=',xmax:1, ', ymax=',ymax:1,);
  321.   {DrawPerimeter;}
  322.   {ShowPerimeter;}
  323.   RestoreState;
  324. end;
  325.  
  326.  
  327. procedure PlotProfile2(integrate:boolean);
  328. var
  329.   xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  330.   width,height,margin,pwidth,pheight:integer;
  331.   count:integer;
  332.   ppv:integer; {Pixels per Value}
  333. begin
  334.   SaveState;
  335.   margin:=40;
  336.   width:=500;
  337.   height:=300;
  338.   GetPlotData(count,ppv,ymin,ymax);
  339.   if count=0 then begin
  340.     PutMessage('No plot data available.');
  341.     exit;
  342.   end;
  343.   if integrate then begin
  344.      ymin:=ymin*ppv;
  345.      ymax:=ymax*ppv;
  346.   end;
  347.   xmin:=0;
  348.   xmax:=count-1;
  349.   SetNewSize(width,height);
  350.   SetForeground(255);
  351.   SetBackground(0);
  352.   MakeNewWindow('Plot');
  353.   pwidth:=width-2*margin;
  354.   pheight:=height-2*margin;
  355.   xscale:=pwidth/(xmax-xmin);
  356.   yscale:=pheight/(ymax-ymin);
  357.   SetForeground(255);
  358.   SetBackground(0); 
  359.   SetLineWidth(1); 
  360.   MoveTo(margin,margin);
  361.   if integrate then for i:=0 to count-1 do
  362.        LineTo(margin+i*xscale,margin+(PlotData[i]*ppv-ymin)*yscale)
  363.   else  for i:=0 to count-1 do
  364.         LineTo(margin+i*xscale,margin+(PlotData[i]-ymin)*yscale);
  365.   MakeRoi(margin,margin,pwidth+1,pheight+2);
  366.   MoveTo(margin,margin);
  367.   LineTo(margin+pwidth,margin);
  368.   MoveTo(margin,margin);
  369.   LineTo(margin,margin+pheight);
  370.   FlipVertical;
  371.   KillRoi;
  372.   SetFont('Geneva');
  373.   SetFontSize(9);
  374.   SetText('Centered');
  375.   MoveTo(margin+4,margin+pheight+12);
  376.   writeln(xmin:1:2);
  377.   MoveTo(margin+pwidth,margin+pheight+12);
  378.   writeln(xmax:1:2);
  379.   SetText('Right Justified');
  380.   MoveTo(margin-2,margin+pheight-5);
  381.   writeln(ymin:1:2);
  382.   MoveTo(margin-2,margin);
  383.   writeln(ymax:1:2);
  384.   RestoreState;
  385. end;
  386.  
  387.  
  388. macro 'Plot Profile';
  389. begin
  390.   PlotProfile2(false);
  391. end;
  392.  
  393. macro 'Plot Integrated Profile';
  394. begin
  395.   PlotProfile2(true);
  396. end;
  397.  
  398.  
  399. macro 'Plot Profile and Display Values';
  400. var
  401.    count, ppv, ymin, ymax, i: integer;
  402.    scale: real;
  403.    unit: string;
  404. begin
  405.    GetScale(scale, unit);
  406.    PlotProfile;
  407.    GetPlotData(count, ppv, ymin, ymax);
  408.    NewTextWindow('Plot Values', 150, 450);
  409.    for i := 0 to count -1 do
  410.        writeln(i / scale:1:3, ' ', PlotData[i]:1:3);
  411. end;
  412.  
  413.  
  414. macro 'Plot Radial Profiles… [R]';
  415. var
  416.   x1,y1,x2,y2,pi,angle,delta:real;
  417.   LineWidth,i,nLines,radius,PlotWidth,PlotHeight:integer;
  418.   MinPlotWidth,hMargin,vMargin,PlotLeft,PlotTop:integer;
  419.   LeftMargin,RightMargin,TopMargin,BottomMargin:integer;
  420.   ImageWindow,PlotWindow:integer;
  421.   nPixels,mean,mode,min,max:real;
  422. begin
  423.   RequiresVersion(1.54);
  424.   SaveState;
  425.   GetLine(x1,y1,x2,y2,LineWidth);
  426.   if x1<0 then begin
  427.     PutMessage('Please select a point by clicking with the line tool.');
  428.     exit;
  429.   end;
  430.   radius:=GetNumber('Radius:',20);
  431.   nLines:=GetNumber('Number of Lines:',8);
  432.   MinPlotWidth:=140;
  433.   pi:=3.14159;
  434.   delta:=2.0*pi/nLines;
  435.   angle:=0.0;
  436.   PlotWidth:=radius;
  437.   if PlotWidth<MinPlotWidth then PlotWidth:=MinPlotWidth;
  438.   PlotHeight:=0.4*PlotWidth;
  439.   SetPlotSize(PlotWidth,PlotHeight);
  440.   MakeOvalRoi(x1-radius,y1-radius,radius*2,radius*2);
  441.   Measure;
  442.   GetResults(nPixels,mean,mode,min,max);
  443.   min:=min-10;
  444.   if min<0 then min:=0;
  445.   max:=max+10;
  446.   if max>255 then max:=255;
  447.   SetPlotScale(cValue(min),cValue(max));
  448.   SetPlotLabels(false);
  449.   hMargin:=5;
  450.   vMargin:=5;
  451.   LeftMargin:=38;
  452.   TopMargin:=10;
  453.   RightMargin:=20;
  454.   BottomMargin:=20;
  455.   PlotLeft:=hMargin-LeftMargin;
  456.   PlotTop:=vMargin-TopMargin;
  457.   SetNewSize(PlotWidth+2*hMargin,PlotHeight*nLines);
  458.   SetForegroundColor(255);
  459.   SetBackgroundColor(0);
  460.   ImageWindow:=PicNumber;
  461.   MakeNewWindow('Plots');
  462.   PlotWindow:=PicNumber;
  463.   SelectPic(ImageWindow);
  464.   for i:=1 TO nLines do begin
  465.     x2:=x1+round(radius*cos(angle));
  466.     y2:=y1+round(radius*sin(angle));
  467.     MakeLineRoi(x1,y1,x2,y2);
  468.     PlotProfile;
  469.     Copy;
  470.     SelectPic(PlotWindow);
  471.     MakeRoi(PlotLeft,PlotTop,PlotWidth+LeftMargin+RightMargin,
  472.           PlotHeight+TopMargin+BottomMargin);
  473.     Paste;
  474.     DoOr;
  475.     PlotTop:=PlotTop+PlotHeight-1;
  476.     SelectPic(ImageWindow);
  477.     angle:=angle+delta;
  478.   end;
  479.   RestoreState;
  480. end;
  481.  
  482.  
  483. macro 'Radial Intensity Distibution…';
  484. var
  485.   x1,y1,x2,y2,pi,angle,delta:real;
  486.   radius,ymin,ymax,sum:real;
  487.   i,j,LineWidth,nLines,count,ppv:integer;
  488. begin
  489.   RequiresVersion(1.54);
  490.   SaveState;
  491.   GetLine(x1,y1,x2,y2,LineWidth);
  492.   if x1<0 then begin
  493.     PutMessage('Please select a point by clicking with the line tool.');
  494.     exit;
  495.   end;
  496.   radius:=GetNumber('Radius (pixels):',50);
  497.   nLines:=GetNumber('Number of Lines:',25);
  498.   for i:= 1 to radius do rUser1[i]:=0;
  499.   pi:=3.14159;
  500.   delta:=2.0*pi/nLines;
  501.   angle:=0.0;
  502.   for i:=1 to nLines do begin
  503.     x2:=x1+round(radius*cos(angle));
  504.     y2:=y1+round(radius*sin(angle));
  505.     MakeLineRoi(x1,y1,x2,y2);
  506.     GetPlotData(count,ppv,ymin,ymax);
  507.     for j:=1 to count do
  508.         rUser1[j]:=rUser1[j]+PlotData[j];
  509.     angle:=angle+delta;
  510.   end;
  511.   RestoreState;
  512.   DoColumnPlot(radius);
  513. end;
  514.  
  515.  
  516. macro 'Circular Profile Plot [C]';
  517. var
  518.   radius,pi,angle,dx,dy,delta:real;
  519.   x1,y1,x2,y2:real;
  520.   npoints,i,value,LineWidth,x,y,px:integer;
  521. begin
  522.   GetLine(x1,y1,x2,y2,LineWidth);
  523.   if x1< 0 then begin
  524.     PutMessage('Please select a point by clicking with the line tool.');
  525.     exit;
  526.   end;
  527.   x:=x1+(x2-x1)/2;
  528.   y:=y1+(y2-y1)/2;
  529.   radius:=sqrt(sqr(x2-x1)+sqr(y2-y1))/2;
  530.   if radius<3 then begin
  531.     PutMessage('The line selection must be longer than 5 pixels.');
  532.     exit;
  533.   end;
  534.   npoints:=radius*2;
  535.   pi:=3.14159;
  536.   delta:=2.0*pi/npoints;
  537.   angle:=0.0;
  538.   px:=0;
  539.   for i:=1 TO npoints do begin
  540.     dx:=round(radius*cos(angle));
  541.     dy:=round(radius*sin(angle));
  542.     value:=GetPixel(x+dx,y+dy);
  543.     PutPixel(x+dx,y+dy,255);
  544.     PutPixel(px,0,value);
  545.     px:=px+1;
  546.     angle:=angle+delta;
  547.   end;
  548.   MakeLineRoi(0,0,npoints,0);
  549.   PlotProfile;
  550.   KillRoi;
  551. end;
  552.  
  553. macro 'Export Profile Plots…';
  554. var
  555.   y,yInc,width,height,n:integer;
  556. begin
  557.   yInc:=GetNumber('Y Increment:',10);
  558.   GetPicSize(width,height);
  559.   y:=0;
  560.   n:=0;
  561.   SetExport('Plot Values');
  562.   repeat
  563.     MakeLineRoi(0,y,width-1,y);
  564.     PlotProfile;
  565.     Export('PLOT',n:4);
  566.     n:=n+1;
  567.     y:=y+yInc;
  568.   until y>=height;
  569. end;
  570.  
  571.  
  572. procedure PlotMeans;
  573. {Plots the mean column in the Results table.}
  574. var
  575.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  576.   width,height,margin,pwidth,pheight:integer;
  577.   y,pbottom:integer;
  578. begin
  579.   margin:=40;
  580.   width:=500;
  581.   height:=300;
  582.   ymax:=-999999;
  583.   ymin:=999999;
  584.   for i:=1 to rCount do begin
  585.     y:=rMean[i];
  586.     if y>ymax then ymax:=y;
  587.     if y<ymin then ymin:=y;
  588.   end;
  589.   xmin:=0;
  590.   xmax:=rCount-1;
  591.   SetNewSize(width,height);
  592.   SetForeground(255);
  593.   SetBackground(0);
  594.   MakeNewWindow('Z-Axis Profile Plot');
  595.   pwidth:=width-2*margin;
  596.   pheight:=height-2*margin;
  597.   pbottom:=margin+pheight;
  598.   xscale:=pwidth/(xmax-xmin);
  599.   yscale:=pheight/(ymax-ymin);
  600.   SetForeground(255);
  601.   SetBackground(0); 
  602.   SetLineWidth(1);
  603.   MoveTo(margin,pbottom-(rMean[1]-ymin)*yscale);
  604.   for i:=2 to rCount do
  605.      LineTo(margin+(i-1)*xscale,pbottom-(rMean[i]-ymin)*yscale);
  606.   MoveTo(margin,pbottom);
  607.   LineTo(margin+pwidth,pbottom);
  608.   MoveTo(margin,margin);
  609.   LineTo(margin,margin+pheight);
  610.   SetFont('Geneva');
  611.   SetFontSize(9);
  612.   SetText('Centered');
  613.   MoveTo(margin+4,margin+pheight+12);
  614.   writeln(xmin:1:2);
  615.   MoveTo(margin+pwidth,margin+pheight+12);
  616.   writeln(xmax:1:2);
  617.   SetText('Right Justified');
  618.   MoveTo(margin-2,margin+pheight-5);
  619.   writeln(ymin:1:2);
  620.   MoveTo(margin-2,margin);
  621.   writeln(ymax:1:2);
  622. end;
  623.  
  624. macro 'Plot Z-Axis Profile [Z]';
  625. {Plots the average density of an roi through a stack.}
  626. var
  627.   left,top,width,height,i:integer;
  628. begin
  629.   if (nPics=0) or (nSlices=0) then begin
  630.      PutMessage('This macro requires a stack.');
  631.      exit;
  632.   end;
  633.   GetRoi(left,top,width,height);
  634.   if width=0 then begin
  635.      PutMessage('Selection required.');
  636.      exit;
  637.   end;
  638.   ResetCounter;
  639.   {SetOptions('Mean');}
  640.   for i:= 1 to nSlices do begin
  641.      SelectSlice(i);
  642.      Measure;
  643.   end;
  644.   PlotMeans;
  645.  end;
  646.  
  647.  
  648. macro 'Plot XYZ';
  649. {
  650. Plots X-Y coordinate points with an optional intensity(Z). Values are read from
  651. a 2 or 3 column tab-delimited text file. Data must be scaled as follows:
  652. 0<=X<width; 0<=Y<height; 0<=Z<=255.
  653. }
  654. var
  655.   width,height:integer;
  656. begin
  657.   SaveState;
  658.   width:=500;
  659.   height:=500;
  660.   SetNewSize(width,height);
  661.   SetForeground(255);
  662.   SetBackground(0);
  663.   MakeNewWindow('Plot');
  664.   PlotXYZ;
  665.   RestoreState;
  666. end;
  667.  
  668. macro 'Draw Fitted Ellipse in White';
  669. var
  670.   left,top,width,height:real;
  671. begin
  672.   GetRoi(left,top,width,height);
  673.   if width=0 then begin
  674.     PutMessage('This macro requires a selection.');
  675.     exit;
  676.   end;
  677.   SetOptions('Area; Mean; X-Y Center');
  678.   Measure;
  679.   SetOption; MarkSelection;
  680.   KillRoi;
  681.   SelectAll;
  682.   KillRoi;
  683.  end;
  684.  
  685. macro 'Draw Calibration Bar [B]';
  686. {Generates a vertical calibration bar with labels.}
  687. var
  688.   top,left,width,height,nLabels,i:integer;
  689.   vloc,fwidth,digits,value:integer;
  690. begin
  691.   SaveState;
  692.   GetRoi(left,top,width,height);
  693.   if width=0 then begin
  694.     PutMessage('This macro requires a selection.');
  695.     exit;
  696.   end;
  697.   if width>height then begin
  698.     PutMessage('Selection must be vertically oriented.');
  699.     exit;
  700.   end;
  701.   nLabels:=round(height/25);
  702.   if nLabels<2 then nLabels:=2;
  703.   SetFontSize(9);
  704.   SetFont('Monaco');
  705.   SetText('Left Justified, With Background');
  706.   DrawScale;
  707.   {FlipVertical;}
  708.   KillRoi;
  709.   SetForeground(255); {black}
  710.   SetBackground(0); {white}
  711.   if calibrated then begin
  712.      fwidth:=7;
  713.     digits:=4;
  714.   end else begin
  715.     fwidth:=3;
  716.     digits:=0;
  717.   end;
  718.   vloc:=top;
  719.   for i:=0 to nLabels-1 do begin
  720.     vloc:=top+round(i*((height-1)/(nLabels-1)));
  721.     if vloc>=(top+height) then vloc:=top+height-1;
  722.     MoveTo(left+width+4,vloc+3);
  723.     value:=cvalue(GetPixel(left,vloc));
  724.     Write(value:fwidth:digits);
  725.     vloc:=vloc+round(height/(nLabels-1));
  726.   end;
  727.   RestoreRoi;
  728.   SetForeground(0); {white}
  729.   InsetRoi(-1);
  730.   DrawBoundary;
  731.   KillRoi;
  732.   RestoreState;
  733. end;
  734.  
  735.  
  736. macro 'Show Polar Coordiates [P]';
  737. {Returns polar coordinates of a point selected with the mouse, using centre 
  738. of the image as 0,0.  Data are displayed in the Info window as distance from 
  739. centre of image, and angle in degrees measured clockwise, where 0 is the 
  740. 12 o'clock position}
  741. var
  742.     Wide, High,x2,y2:integer;
  743.     x1,y1,D,Theta,rad:real;
  744. begin
  745.    rad:=180/3.14159265;
  746.    InvertY(true);
  747.    GetPicSize(Wide,High);
  748.    SetCursor('cross');
  749.    repeat
  750.       GetMouse(x2,y2);
  751.       x1:=Wide/2;
  752.       y1:=High/2;
  753.       y2:=High-y2
  754.       if (x1=x2) and (y1=y2) then begin
  755.          D:=0;
  756.          Theta:=0;
  757.       end;
  758.       if (y1<>y2) then begin
  759.          D:= sqrt((sqr(x2-x1))+ (sqr(y2-y1)));
  760.          Theta:=rad*(arctan((x2-x1)/(y2-y1)));
  761.       end;
  762.       if (y2<y1) then begin
  763.          Theta:=180 + Theta; 
  764.       end;
  765.       if (x2<x1) and (y2>y1) then begin
  766.          Theta:=360+Theta;
  767.       end;
  768.       ShowMessage('Distance: ',D:5:1'\''Angle: ',Theta:5:1); 
  769.       Wait(0.2);
  770.    until button;
  771. end;
  772.  
  773.  
  774. macro 'Record XY [X]';
  775. {Records the X-Y Coordinates of each pixel in the perimeter
  776. of a particle (selected with the wand) and saves the data to a
  777. comma-delimited text file}
  778. var
  779.     i,w,h:real;
  780.    xbase,ybase,width,height,RoiWidth,RoiHeight:real
  781.    x,y,xmax,ymax:real 
  782. begin
  783.    GetPicSize(width,height);
  784.    GetRoi(xbase,ybase,RoiWidth,RoiHeight);
  785.     if (RoiWidth=0) or (nCoordinates=0) then begin
  786.       PutMessage('Select a particle with the wand.');
  787.        exit;
  788.    end;
  789.   InvertY(false);
  790.    NewTextWindow('XY Data',150,400);
  791.    for i:=1 to nCoordinates do
  792.       Writeln(i,',',xCoordinates[i]+xbase:5:0,',',Height-yCoordinates[i]-ybase:5:0);
  793. end;
  794.  
  795.  
  796. procedure WriteReal(r:real);
  797. {Writes a real number using scientific notation.}
  798. var
  799.   e: integer;
  800. begin
  801.   e := 0;
  802.   while r >= 10 do begin
  803.     r := r / 10;
  804.     e := e + 1;
  805.   end;
  806.   while r < 1 do begin
  807.     r := r * 10;
  808.     e := e - 1;
  809.   end;
  810.   write(r:8:6);
  811.   if e >= 0 then
  812.                 write('e+')
  813.   else begin
  814.     e := -e;
  815.                 write('e-')
  816.   end;
  817.   if e <10 then
  818.      write('0');
  819.   write(e:1);
  820. end;
  821.  
  822.  
  823. macro 'Write Real Test...';
  824. var
  825.   r: real;
  826. begin
  827.   r := GetNumber('Enter a real number:', 1.234);
  828.   NewTextWindow('Output');
  829.   WriteReal(r);
  830. end;
  831.  
  832.  
  833. macro 'Make Image Correlation Plot...';
  834. {Generates an XY plot indicating how well correlated two images are.  
  835. It uses the z-value of a given pixel in a certain slice as the x-coordinate; 
  836. z-value of the corresponding pixel in another slice as the y-coordinate.  
  837. These are plotted into a new window to give a scatter plot.  The 
  838. percentage done is shown in the Info window.}
  839.  
  840. var
  841.    xmin, xmax, ymin, ymax, xscale, yscale, Percent: real;
  842.    xslice, yslice, nPixels, ticks: integer;
  843.    width, height, x, y, xvalue, yvalue, Pointvalue: integer;
  844.    wide, high, StackID, PlotID, margin, ticksize: integer;
  845.    time: real;
  846. begin
  847.    if nSlices=0 then begin
  848.       beep;
  849.       PutMessage('This macro requires a stack.');
  850.       exit
  851.    end;
  852.    SaveState;
  853.    InvertY(true);
  854.    KillRoi;
  855.    GetPicSize(wide, high);
  856.    nPixels:=wide * high;
  857.    Measure;
  858.    StackID := PidNumber;
  859.    xslice := GetNumber('Slice to plot on the x-axis:', 1);
  860.    yslice := GetNumber('Slice to plot on the y-axis:', 2);
  861.    width := 256;
  862.    height := 256;
  863.    SetNewSize(width,height);
  864.    SetForeground(255);
  865.    SetBackground(0);
  866.    MakeNewWindow('Plot');
  867.    InvertY(true);
  868.    PlotID := PicNumber;
  869.    SelectPic(StackID);
  870.    SetCursor('watch');
  871.    ticks := TickCount;
  872.  
  873.    for y := 0 to high - 1 do begin
  874.       for x := 0 to wide - 1 do begin
  875.          ChoosePic(StackID);
  876.          ChooseSlice(xslice);
  877.          xvalue:=GetPixel(x, y);  {ie z-value of pixel (x,y) on one slice}
  878.          ChooseSlice(yslice);
  879.          yvalue:=GetPixel(x, y); {ie z-value of same pixel on other slice}
  880.          ChoosePic(PlotID);
  881.          Pointvalue := GetPixel(xvalue, 255 - yvalue);
  882.          if PointValue < 254
  883.             then PointValue:=PointValue+1;
  884.          PutPixel(xvalue, 255 - yvalue, PointValue);
  885.      end; {for x...}
  886.      if (y mod 10) = 0
  887.          then ShowMessage((y / high) * 100:2:0, '% done');
  888.    end;  {for y...}
  889.  
  890.    time := (TickCount-ticks) / 60;
  891.    ShowMessage(nPixels:1,  ' pixels\',  time:1:2,  ' seconds\',
  892.       nPixels/time:1:0,  ' pixels/second');
  893.  
  894.    SelectPic(StackID);
  895.    SelectSlice(xSlice);
  896.    SelectPic(PlotID);
  897.    SelectAll;
  898.    EnhanceContrast;
  899.    ApplyLut;
  900.    SelectAll;
  901.    Copy;
  902.    Dispose;
  903.    margin := 75;
  904.    ticksize := 6;
  905.    SetNewSize(width + (2 * margin), height + (2 * margin));
  906.    SetForeground(255);
  907.    SetBackground(0);
  908.    MakeNewWindow('Correlation Plot');
  909.    SetFont('Geneva');
  910.    SetFontSize(9);
  911.    InvertY(true);
  912.    MakeRoi(margin, margin, 256, 256);
  913.    Paste;
  914.    MakeRoi(margin - 1, margin - 1, 258, 258);
  915.    SetLinewidth(1); 
  916.    DrawBoundary;
  917.    KillRoi;
  918.    MoveTo(margin, margin + 255);
  919.    LineTo(margin, margin + 255 + ticksize);
  920.    MoveTo(margin + 50, margin + 256);
  921.    LineTo(margin + 50, margin + 256 + ticksize);
  922.    MoveTo(margin + 100, margin + 256);
  923.    LineTo(margin + 100, margin + 256 + ticksize);
  924.    MoveTo(margin +150, margin + 256);
  925.    LineTo(margin + 150, margin + 256 + ticksize);
  926.    MoveTo(margin + 200, margin + 256);
  927.    LineTo(margin + 200, margin + 256 + ticksize);
  928.    MoveTo(margin + 255, margin + 256);
  929.    LineTo(margin + 255, margin + 256 + ticksize);
  930.    MoveTo(margin - 1, margin + 255);
  931.    LineTo(margin - ticksize, margin + 255);
  932.    MoveTo(margin - 1, margin + 206);
  933.    LineTo(margin - ticksize, margin + 206);
  934.    MoveTo(margin -1 , margin + 156);
  935.    LineTo(margin - ticksize, margin + 156);
  936.    MoveTo(margin - 1, margin + 106);
  937.    LineTo(margin - ticksize, margin + 106);
  938.    MoveTo(margin - 1, margin + 56);
  939.    LineTo(margin - ticksize, margin + 56);
  940.    MoveTo(margin - 1, margin);
  941.    LineTo(margin - ticksize, margin);
  942.    MoveTo(margin - 25, margin);
  943.    Writeln('255');
  944.    MoveTo(margin - 25, margin + 56);
  945.    Writeln('200');
  946.    MoveTo(margin - 25, margin + 156);
  947.    Writeln('100');
  948.    MoveTo(margin - 14, margin + 256);
  949.    Writeln('0');
  950.    MoveTo(margin - 2, margin + 270);
  951.    Writeln('0');
  952.    MoveTo(margin + 92, margin + 270);
  953.    Writeln('100');
  954.    MoveTo(margin + 192, margin + 270);
  955.    Writeln('200');
  956.    MoveTo(margin + 248, margin + 270);
  957.    Writeln('255');
  958.    MoveTo(margin + 70, margin + 290);
  959.    Writeln('Z-value on slice', xslice:1);
  960.    MoveTo(margin - 65, margin + 100);
  961.    Writeln('Z-value');
  962.    MoveTo(margin - 65, margin + 115);
  963.    Writeln('on slice', yslice:1);
  964.  
  965.    RestoreState;
  966. end;
  967.  
  968.  
  969.  
  970.